home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 140 / Gekkan Dennou Club - 2000.1 Vol. 140 (Japan).7z / Gekkan Dennou Club - 2000.1 Vol. 140 (Japan) (Track 1).bin / tools / dshell / dsh333bs.lzh / event.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-09  |  24.4 KB  |  1,364 lines

  1. /*
  2.     dshell    v3
  3.  
  4.     DSHELLコントロール
  5. */
  6.  
  7. #include    "dsh.h"
  8.  
  9. #define    SSCRL    FALSE
  10.  
  11. static void On_Menubar1(int);
  12. static void On_Menubar2(int);
  13. static void On_Main_Screen(int, int);
  14. static void Fkey_Down_Check(int *, int *, uchar []);
  15. static void Ctrl_Down(int, int);
  16. static void line_b(void);
  17. static void line_f(void);
  18.  
  19. void check_keysns(void);
  20.  
  21. // v3.30
  22. enum {
  23.     ONEKEY_CONT = 0,
  24.     ONEKEY_EXEC = 1,
  25.     ONEKEY_RETN = -1,
  26. };
  27. static uchar selectedFlag;    // TRUE...'◎' が見つかった
  28. static uchar backwardFlag;    // TRUE...後方検索/実行
  29. static int ontime;    // 現在時刻 (起動時からの経過日時)
  30. static int etMenu;    // 最下行メニューリピート用
  31. static int etTab;    // TAB/XF3/XF4 リピート用
  32.  
  33. static int keyEvent(int *, int *, ushort);
  34. static int oneKeyView(int, int, uchar);
  35. static int checkOneKeyView(void);
  36. static void locateTypeLine(int, int);
  37. static int isTypeLine(const uchar *);
  38. static void p_mark(int);
  39. static void callDtype(int);
  40. static void callDexec(const char *, int);
  41. static void adjMspos(void);
  42. static void inOutDebugMode(void);
  43. void locateEol(int);
  44.  
  45. // v3.33a
  46. static int checkRapidExec(void);
  47.  
  48.  
  49. /*
  50.     DSHELL コントロール
  51.  
  52.     (global)nest:    階層
  53.     (global)lhp:    テキスト行ポインタテーブルへのポインタ
  54.     (global)lp:    表示開始行
  55.     (global)lpmx:    最大行数
  56. */
  57. static int dmx, dmy, bl, br;
  58. static char obl, obr;
  59.  
  60. int
  61. get_event(void)
  62. {
  63.     static uchar *markedText = NULL;    // == lhp[0] なら先頭/末尾で自動実行停止
  64.     static ushort shiftKeys;
  65.     int x, y;
  66.  
  67. /*    lp = 0;        ; lp はget_event()呼出前に初期化済のこと */
  68.  
  69.     bl = br = 0;
  70.     etMenu = etTab = 0;
  71.     selectedFlag = FALSE;
  72.     curLine = 0;
  73.     exeLine = -1;
  74.     if (lp1st >= 0) {
  75.         lp = lp1st;
  76.         lp1st = -1;
  77.         if (lp >= lpmx) {
  78.             lp = lpmx - 30;
  79.             if (lp < 0)
  80.                 lp = 0;
  81.         }
  82.     }
  83.     curLine = lp;
  84.  
  85.     if (checkRapidExec())
  86.         return 0;
  87.  
  88.     p_fukki();
  89.     p_scr();
  90.     p_fpt(1);
  91.     wait_mb_off();
  92.     clr_kbf();
  93.     mouse(1);
  94.  
  95.     while (1) {
  96.         ontime = d_ontime();
  97.         shiftKeys = B_SFTSNS();
  98.         check_keysns();
  99.  
  100.         p_time(0);
  101.         obl = bl;
  102.         obr = br;
  103.         dmspos(&x, &y);
  104.         dmsstat(&dmx, &dmy, &bl, &br);
  105.  
  106.         /*
  107.             スペースによる1キー閲覧
  108.             コード入力キーによる自動実行
  109.         */
  110.         if (checkOneKeyView()) {
  111.             ushort stepFlag = FALSE;
  112.  
  113.             backwardFlag = (shiftKeys & SHIFT_KEY);
  114.             if (debugMode) {
  115.                 if (shiftKeys & LED_CODEIN) {
  116.                     backwardFlag = !!(shiftKeys & LED_ZENKAKU);
  117.                     if (shiftKeys & LED_INS) {
  118.                         w_wait(20);
  119.                         w_wait(20);
  120.                     }
  121.                 } else {
  122.                     if (shiftKeys & LED_ZENKAKU)
  123.                         backwardFlag ^= SHIFT_KEY;
  124.                     stepFlag = ((shiftKeys & (OPT1_KEY | OPT2_KEY | SHIFT_KEY)) == OPT1_KEY);
  125.                     if ((shiftKeys & (OPT1_KEY | OPT2_KEY | SHIFT_KEY)) == OPT2_KEY) {
  126.                         markedText = lhp[0];
  127.                         LEDMOD(2, 1);
  128.                     } else
  129.                         markedText = NULL;
  130.                 }
  131.             }
  132.             switch (oneKeyView(x, y, TRUE)) {
  133.             case ONEKEY_CONT:
  134.                 break;
  135.             case ONEKEY_EXEC:
  136.                 if (stepFlag)
  137.                     LEDMOD(2, 1);
  138.                 mspos(&x, &y);
  139.                 if (x < 16 && y >= 1*16 && y < 31*16)
  140.                     setmspos(16, y);
  141.                 lp1st = (backwardFlag) ? INT_MAX : 0;
  142.                 callDtype(curLine);
  143.                 lp1st = -1;
  144.                 setmspos(x, y);
  145.                 if (stepFlag)
  146.                     LEDMOD(2, 0);
  147.                 oneKeyView(x, y, FALSE);
  148.                 break;
  149.             case ONEKEY_RETN:
  150.                 if (debugMode && (shiftKeys & LED_CODEIN)
  151.                   && (!nest || lhp[0] == markedText)) {
  152.                     LEDMOD(2, 0);
  153.                     B_PUTC('\a');
  154.                     break;
  155.                 }
  156.                 if (nest)
  157.                     return 0;
  158.                 break;
  159.             }
  160.             if (selectedFlag && isTypeLine(lhp[curLine]))
  161.                 p_mark(curLine - lp);
  162.             continue;
  163.         }
  164.  
  165.  
  166.         /*
  167.             各種キー操作
  168.         */
  169.         if (!bl && !br) {
  170.             if (keyEvent(&x, &y, shiftKeys) < 0)
  171.                 return lp + 1;    // 登録キー
  172.         } else
  173.             etTab = 0;
  174.         if (y >= 1*16 && y < 31*16 && !bl && !br)
  175.             obl = obr = 0;
  176.  
  177.  
  178.         /*
  179.         !    左端にカーソルがあっても復帰出来るようにする
  180.         !    ESCでも同じです。(仮想マウスの方で対処している)
  181.         */
  182.         if ((bl) && (br)) {    /* 両方のボタンクリック */
  183.             if (nest)
  184.                 return 0;
  185.             do {
  186.                 dmsstat(&dmx, &dmy, &bl, &br);
  187.             } while (bl && br);    /* どちらかのボタンが離されるのを待つ */
  188.             continue;
  189.         }
  190.  
  191.  
  192.         if (y < 1*16) {
  193.         /*
  194.         !    上メニューバー
  195.         */
  196.             p_fpt(3);
  197.             if (!obl && !obr)
  198.                 On_Menubar1(x);
  199.         } else if (y >= 31*16) {
  200.         /*
  201.         !    下メニューバー
  202.         */
  203.             p_fpt(4);
  204.             if (etMenu <= ontime || (!obl && !obr)) {
  205.                 if (GMODE) {
  206.                     if (bl && nest && x >= 59 * 8 && x < 63 * 8) {
  207.                         return 0;
  208.                     } else {
  209.                         On_Menubar2(x);
  210.                     }
  211.                 } else {
  212.                     if (bl && nest && x >= 90 * 8 && x < 94 * 8) {
  213.                         return 0;
  214.                     } else {
  215.                         On_Menubar2(x);
  216.                     }
  217.                 }
  218.             }
  219.         } else {
  220.         /*
  221.         !    メインスクリーン上
  222.         */
  223.             On_Main_Screen(x, y);
  224.         }
  225.     }
  226. }
  227.  
  228.  
  229. /*
  230.     キーイベント
  231. */
  232. static int
  233. keyEvent(int *xp, int *yp, ushort shiftKeys)
  234. {
  235.     int i, x, y;
  236.     uchar bitKeys[14];
  237.  
  238.     x = *xp;
  239.     y = *yp;
  240.     for (i = 0; i < sizeof(bitKeys); i++)
  241.         bitKeys[i] = BITSNS(i);
  242.  
  243.     /*
  244.         TAB/XF3/XF4 による '◎' の検索
  245.     */
  246.     if (bitKeys[2] == (1<<0)) {    // TAB
  247.         if (etTab <= ontime) {
  248.             if (debugMode && (shiftKeys & LED_ZENKAKU))
  249.                 shiftKeys ^= SHIFT_KEY;
  250.             backwardFlag = (shiftKeys & SHIFT_KEY);
  251.             locateTypeLine(x, y);
  252.         }
  253.         return 0;
  254.     } else if (bitKeys[10] == (1<<7)) {    // XF3
  255.         if (etTab <= ontime) {
  256.             backwardFlag = (shiftKeys & SHIFT_KEY);
  257.             locateTypeLine(x, y);
  258.         }
  259.         return 0;
  260.     } else if (bitKeys[11] == (1<<0)) {    // XF4
  261.         if (etTab <= ontime) {
  262.             backwardFlag = !(shiftKeys & SHIFT_KEY);
  263.             locateTypeLine(x, y);
  264.         }
  265.         return 0;
  266.     }
  267.     etTab = 0;
  268.  
  269.     /*
  270.     !    CTRLキーで一番近い◎に移動する
  271.     */
  272.     if (shiftKeys & CTRL_KEY) {
  273.         Ctrl_Down(x, y);
  274.         while (ctrl_on())
  275.             ;
  276.         return 0;
  277.     }
  278.  
  279.     /*
  280.         CLR/DEL によるグラフィック画面/テキスト画面 ON/OFF
  281.     */
  282.     if (GMODE) {
  283.         if (bitKeys[7] == (1<<7)) {    // CLR
  284.             g_pop();
  285.             return 0;
  286.         }
  287.         if (bitKeys[6] == (1<<7)) {    // DEL
  288.             if (g_disp() == TRUE)
  289.                 g_off();
  290.             else
  291.                 g_on();
  292.             while (del_on())
  293.                 ;
  294.             return 0;
  295.         }
  296.     }
  297.  
  298.     /*
  299.         HELP によるオンラインマニュアル起動
  300.         OPT.2+HELP によるデバッグモード ON/OFF
  301.     */
  302.     if (bitKeys[10] == (1<<4)) {    // HELP
  303.         if (shiftKeys & OPT2_KEY)    // OPT.1+HELP
  304.             inOutDebugMode();
  305.         else
  306.             onlinemanual();
  307.         while (help_on())
  308.             ;
  309.         return 0;
  310.     }
  311.  
  312.     /*
  313.         'P'('V') 'S' 'C' 各キーによる音楽演奏制御
  314.     */
  315.     if (bitKeys[3] == (1<<2)        // 'P'
  316.       || bitKeys[5] == (1<<5)) {    // 'V'
  317.         dm_play('PLAY');
  318.         while (BITSNS(3) || BITSNS(5))
  319.             ;
  320.         return 0;
  321.     } if (bitKeys[5] == (1<<6)) {    // 'B'
  322.         dm_play('STOP');
  323.         while (BITSNS(5))
  324.             ;
  325.         return 0;
  326.     } if (bitKeys[5] == (1<<4)) {    // 'C'
  327.         dm_play('CONT');
  328.         while (BITSNS(5))
  329.             ;
  330.         return 0;
  331.     }
  332.  
  333.     /*
  334.         デバッグモードにおける登録キーによるエディタの呼び出し
  335.     */
  336.     if (debugMode && bitKeys[10] == (1<<3)) {    // 登録キー
  337.         lp1st = lp;
  338.         return -1;
  339.     }
  340.  
  341.     /*
  342.     !    ファンクションキー呼び出し
  343.     */
  344.     Fkey_Down_Check(xp, yp, bitKeys);
  345.  
  346.     return 0;
  347. }
  348.  
  349.  
  350. /*
  351.     メニューバー上の時のイベント
  352. */
  353. static void
  354. On_Menubar1(int mx)
  355. {
  356.     mx /= 8;
  357.  
  358.     if (GMODE) {        /* ** 64桁 G-mode ** */
  359.         if (bl) {
  360.             if (1 <= mx && mx < 5) {    /* グラフィック画面表示 */
  361.                 if (g_disp()== TRUE) {
  362.                     g_pop();
  363.                 } else {
  364.                     g_on();
  365.                 }
  366.             } else if (7 <= mx && mx < 47) {    /* ファイル名 */
  367.                 p_file();
  368.             } else if (51 <= mx && mx < 56) {    /* child */
  369.                 callDexec("", DEX_PSCR | DEX_FKON | DEX_RETM | DEX_SHELL);
  370.                 p_fukki();
  371.             } else if (59 <= mx && mx < 62) {    /* 終了 */
  372.                 setenv_and_export("DSHELLSTAT", "");
  373.                 dend();
  374.             }
  375.         } else if (br) {
  376.             if (1 <= mx && mx < 5) {    /* グラフィック画面表示 */
  377.                 if (g_disp()== TRUE) {
  378.                     g_off();
  379.                 } else {
  380.                     g_on();
  381.                 }
  382.             } else if (7 <= mx && mx < 47) {    /* version */
  383.                 p_ver();
  384.             }
  385.         }
  386.     } else {        /* ** 96桁 ** */
  387.         if (bl) {
  388.             if (2 <= mx && mx < 22) {    /* 起動してからの時間表示 */
  389.                 p_otm();
  390.             } else if (28 <= mx && mx < 68) {    /* ファイル名 */
  391.                 p_file();
  392.             } else if (81 <= mx && mx < 86) {    /* Child */
  393.                 callDexec("", DEX_PSCR | DEX_FKON | DEX_RETM | DEX_SHELL);
  394.                 p_fukki();
  395.             } else if (90 <= mx && mx < 94) {    /* 終了 */
  396.                 setenv_and_export("DSHELLSTAT", "");
  397.                 dend();
  398.             }
  399.         } else if (br) {
  400.             if (2 <= mx && mx < 22) {    /* フリーエリアのサイズ表示 */
  401.                 p_freearea();
  402.             } else if (28 <= mx && mx < 68) {    /* version */
  403.                 p_ver();
  404.             }
  405.         }
  406.     }
  407. }
  408.  
  409. /*
  410.     メニューバー下のイベント
  411. */
  412. static void
  413. On_Menubar2(int mx)
  414. {
  415.     int a;
  416.  
  417.     etMenu = init_et(40);
  418.     mx /= 8;        /* バイトキャラクタレベルで判定 */
  419.  
  420.     /*
  421.     !    レフトダウン
  422.     */
  423.     if (bl) {
  424.         if (mx >= 2 && mx < 6) {    /* 先頭行 */
  425.             selectedFlag = FALSE;
  426.             curLine = exeLine = -1;
  427.             if (lp) {
  428.                 lp = 0;
  429.                 p_scr();
  430.                 p_fpt(0);
  431.             } else
  432.                 p_norev();
  433.             adjMspos();
  434.         } else if (mx >= 9 && mx < 13) {    /* 次の頁 */
  435.             if (lp < lpmx - 30) {
  436.                 lp += scrlin;
  437.                 if (lp > lpmx - 30) {
  438.                     lp = lpmx - 30;
  439.                 }
  440.                 p_scr();
  441.                 p_fpt(0);
  442.             }
  443.             adjMspos();
  444.             if (obl && !obr)
  445.                 etMenu = init_et(20);
  446.         } else if (mx >= 16 && mx < 20) {    /* 次の区 */
  447.             for (a = lp + 1; a < lpmx; a++) {
  448.                 if (lhp[a][0] == CTRL_CHAR && lhp[a][1] == HR_CHAR)
  449.                     break;
  450.             }
  451.             if (a >= lpmx) {
  452.                 if (lp >= lpmx - 30)
  453.                     return;
  454.                 a = lpmx - 30;
  455.             }
  456.             lp = a;
  457.             p_scr();
  458.             p_fpt(0);
  459.             adjMspos();
  460.             if (obl && !obr)
  461.                 etMenu = init_et(20);
  462.         } else if (mx >= 23 && mx < 27) {    /* 次行 */
  463.             line_f();
  464.             if (obl && !obr)
  465.                 etMenu = 0;
  466.         }
  467.         if (GMODE == 0) {
  468.             if (mx >= 30 && mx < 33) {    /* RGBメニュー */
  469.                 Menu_rgb();
  470.                 p_fukki();
  471.             } else if (mx >= 35 && mx < 39) {    /* MESHメニュー */
  472.                 Menu_mesh();
  473.                 p_fukki();
  474.             } else if (mx >= 41 && mx < 45) {    /* FINDメニュー */
  475.                 Menu_find();
  476.                 p_fukki();
  477.             } else if (mx >= 47 && mx < 51) {    /* FILEメニュー */
  478.                 Menu_file();
  479.                 p_fukki();
  480.             }
  481.         } else {
  482.             if (mx == 64) {            /* FINDメニュー */
  483.                 Menu_find();
  484.                 p_fukki();
  485.             } else if (mx == 65) {        /* FILEメニュー */
  486.                 Menu_file();
  487.                 p_fukki();
  488.             }
  489.         }
  490.         if ((GMODE && mx >= 49 && mx < 53) || (!GMODE && mx >= 53 && mx < 57)) {    /* 印刷メニュー */
  491.             prn_menu(GMODE ? 49 : 53);
  492.             p_fukki();
  493.         } else if ((GMODE && mx >= 54 && mx < 58) || (!(GMODE) && mx >= 59 && mx < 63)) {
  494.             menu(GMODE ? 54 : 59);
  495.             p_fukki();
  496.         }
  497.         if (!(GMODE)) {
  498.             if (mx >= 66 && mx < 80) {    /* リアルタイムスクロール */
  499.                 if (lpmx > 30) {
  500.                     Realtime_Scroll();
  501.                 }
  502.             }
  503.         }
  504.     }
  505.     /*
  506.     !    ライトダウン
  507.     */
  508.     else if (br) {
  509.         if (mx >= 2 && mx < 6) {    /* 最終行 */
  510.             selectedFlag = FALSE;
  511.             curLine = exeLine = lpmx;
  512.             if (lp < lpmx - 30) {
  513.                 lp = (lpmx - 30 < 0) ? 0 : lpmx - 30;
  514.                 p_scr();
  515.                 p_fpt(0);
  516.             } else
  517.                 p_norev();
  518.             adjMspos();
  519.         } else if (mx >= 9 && mx < 13) {    /* 前の頁 */
  520.             if (lp) {
  521.                 lp -= scrlin;
  522.                 if (lp < 0) {
  523.                     lp = 0;
  524.                 }
  525.                 p_scr();
  526.                 p_fpt(0);
  527.             }
  528.             adjMspos();
  529.             if (obr & !obl)
  530.                 etMenu = init_et(20);
  531.         } else if (mx >= 16 && mx < 20) {    /* 前の区 */
  532.             if (lp > 0) {
  533.                 for (a = lp - 1; a > 0; a--) {
  534.                     if (lhp[a][0] == CTRL_CHAR && lhp[a][1] == HR_CHAR)
  535.                         break;
  536.                 }
  537.                 lp = a;
  538.                 p_scr();
  539.                 p_fpt(0);
  540.             }
  541.             adjMspos();
  542.             if (obr && !obl)
  543.                 etMenu = init_et(20);
  544.         } else if (mx >= 23 && mx < 27) {    /* 前行 */
  545.             line_b();
  546.             if (obr && !obl)
  547.                 etMenu = 0;
  548.         } else if ((GMODE && mx >= 54 && mx < 58) || (!(GMODE) && mx >= 59 && mx < 63)) {
  549.             localMenu(GMODE ? 54 : 59);
  550.             p_fukki();
  551.         }
  552.     }
  553. }
  554.  
  555. /*
  556.     メインスクリーン上でのイベント
  557. */
  558. static void 
  559. On_Main_Screen(int mx, int my)
  560. {
  561.     p_fpt(0);    /* リアルタイム行数表示(マウスカーソル位置) */
  562.  
  563.     /*
  564.     !    レフトボタン
  565.     */
  566.     if (bl) {
  567.         if (mx < 16) {
  568.             dmsstat(&dmx, &dmy, &bl, &br);
  569.             if (bl || (msbtn(0, 0, 0) && msbtn(1, 0, 60) > 0)) {
  570.                 callDtype(lp + my / 16 - 1);
  571.             }
  572.         } else {
  573.             line_f();
  574.         }
  575.     }
  576.     /*
  577.     !    ライトボタン
  578.     */
  579.     if (br) {
  580.         if (mx >= 16) {
  581.             line_b();
  582.         }
  583.     }
  584. }
  585.  
  586. /*
  587.     ファンクションキーの読みだしルーチン
  588.     強引にマウスの座標を変える(カーソルの位置は変わらない)
  589. */
  590. static void
  591. Fkey_Down_Check(int *xp, int *yp, uchar bitKeys[])
  592. {
  593. #define        TX(x)        ((x)*8)
  594. #define        M_BAR1        0
  595. #define        M_BAR2        496
  596.     int x = *xp;
  597.     int y = *yp;
  598.  
  599.     switch (bitKeys[0x0c]) {
  600.     case 0x08:
  601.         x = TX(4);
  602.         y = M_BAR2;
  603.         bl = -1;
  604.         break;        /* F.1:ScrUp    */
  605.     case 0x10:
  606.         x = TX(4);
  607.         y = M_BAR2;
  608.         br = -1;
  609.         break;        /* F.2:ScrDown    */
  610.     case 0x20:
  611.         x = TX(11);
  612.         y = M_BAR2;
  613.         bl = -1;
  614.         break;        /* F.3:NextPage    */
  615.     case 0x40:
  616.         x = TX(11);
  617.         y = M_BAR2;
  618.         br = -1;
  619.         break;        /* F.4:PrevPage    */
  620.     case 0x80:
  621.         x = TX(18);
  622.         y = M_BAR2;
  623.         bl = -1;
  624.         break;        /* F.5:NextArea    */
  625.     default:
  626.         break;
  627.     }
  628.     if (GMODE) {
  629.         switch (bitKeys[0x0d]) {
  630.         case 0x01:
  631.             x = TX(18);
  632.             y = M_BAR2;
  633.             br = -1;
  634.             break;    /* F.6:PrevArea    */
  635.         case 0x02:
  636.             x = TX(25);
  637.             y = M_BAR2;
  638.             bl = -1;
  639.             break;    /* F.7:NextLin    */
  640.         case 0x04:
  641.             x = TX(25);
  642.             y = M_BAR2;
  643.             br = -1;
  644.             break;    /* F.8:PrevLin    */
  645.         case 0x08:
  646.             x = TX(52);
  647.             y = M_BAR1;
  648.             bl = -1;
  649.             break;    /* F.9:ChildProc */
  650.         case 0x10:
  651.             x = TX(61);
  652.             y = M_BAR1;
  653.             bl = -1;
  654.             break;    /* F.10:Exit    */
  655.         default:
  656.             if (bitKeys[3] == (1<<7)) {    // S:FIND
  657.                 x = TX(64);
  658.                 y = M_BAR2;
  659.                 bl = -1;
  660.             } else if (bitKeys[4] == (1<<1)) {    // F:LOAD
  661.                 x = TX(65);
  662.                 y = M_BAR2;
  663.                 bl = -1;
  664.             }
  665.             break;
  666.         }
  667.     } else {
  668.         switch (bitKeys[0x0d]) {
  669.         case 0x01:
  670.             x = TX(18);
  671.             y = M_BAR2;
  672.             br = -1;
  673.             break;    /* F.6:PrevArea    */
  674.         case 0x02:
  675.             x = TX(25);
  676.             y = M_BAR2;
  677.             bl = -1;
  678.             break;    /* F.7:NextLin    */
  679.         case 0x04:
  680.             x = TX(25);
  681.             y = M_BAR2;
  682.             br = -1;
  683.             break;    /* F.8:PrevLin    */
  684.         case 0x08:
  685.             x = TX(83);
  686.             y = M_BAR1;
  687.             bl = -1;
  688.             break;    /* F.9:ChildProc */
  689.         case 0x10:
  690.             x = TX(92);
  691.             y = M_BAR1;
  692.             bl = -1;
  693.             break;    /* F.10:Exit    */
  694.         default:
  695.             if (bitKeys[3] == (1<<7)) {    // S:FIND
  696.                 x = TX(41);
  697.                 y = M_BAR2;
  698.                 bl = -1;
  699.             } else if (bitKeys[4] == (1<<1)) {    // F:LOAD
  700.                 x = TX(47);
  701.                 y = M_BAR2;
  702.                 bl = -1;
  703.             }
  704.             break;
  705.         }
  706.     }
  707.  
  708.     *xp = x;
  709.     *yp = y;
  710. }
  711.  
  712. /*
  713.     一番近い「◎」にカーソルを移動する
  714. */
  715. static void
  716. Ctrl_Down(int mx, int my)
  717. {
  718.     int i;
  719.  
  720.     my = my / 16 - 1;
  721.     if (my < 0)
  722.         my = 0;
  723.     else if (my > 29)
  724.         my = 29;
  725.     if (my + lp > lpmx)
  726.         my = lpmx - lp;
  727.  
  728.     for (i = 0;; i++) {
  729.         if (my + i < 30 && my + i + lp < lpmx) {    /* 下に向かって探す */
  730.             if (isTypeLine(lhp[lp + my + i])) {
  731.                 i = my + i;
  732.                 goto SELECT;
  733.             }
  734.         }
  735.         if ((my - i) >= 0 && lp + my - i < lpmx) {    /* 上に向かって探す */
  736.             if (isTypeLine(lhp[lp + my - i])) {
  737.                 i = my - i;
  738.                 goto SELECT;
  739.             }
  740.         }
  741.         if ((my - i) < 0 && ((my + i >= 30) || (lp + i + my >= lpmx))) {    /* ◎がなかった */
  742.             break;
  743.         }
  744.     }
  745.     return;
  746.  
  747. SELECT:
  748.     curLine = lp + i;
  749.     exeLine = -1;
  750.     selectedFlag = TRUE;
  751.     setmspos(8, (i + 1) * 16 + 8);
  752.     p_mark(i);
  753. }
  754.  
  755.  
  756. /*
  757.     後方スクロール
  758. */
  759. static void 
  760. line_b(void)
  761. {
  762.     if (lp > 0) {
  763.         lp--;
  764. #if SSCRL
  765.         TXRASCPY(119 * 256 + 120, 116, 0x8003);
  766.         w_hs();
  767.         TXRASCPY(120 * 256 + 121, 116, 0x8003);
  768.         w_hs();
  769.         TXRASCPY(121 * 256 + 122, 116, 0x8003);
  770.         w_hs();
  771.         TXRASCPY(122 * 256 + 123, 116, 0x8003);
  772.         w_hs();
  773.         p_lin(lp, 0);
  774. #else
  775.         if (!shift_on()) {
  776. #define    D    56
  777.             p_lin(lp, 62);
  778.             TXRASCPY((120 - D) * 256 + 128, D, 3);
  779.             vsync();
  780.             TXRASCPY((120 - 1 - D) * 256 + (124 - 1 - D), 116 - D, 0x8003);
  781.             TXRASCPY((256 - 4) * 256 + 4, 4, 3);
  782.             TXRASCPY(128 * 256 + (124 - D), D, 3);
  783. #undef    D
  784.         } else {
  785.             TXRASCPY((120 - 1) * 256 + (124 - 1), 116, 0x8003);
  786.             p_lin(lp, 0);
  787.         }
  788. #endif
  789.     }
  790. }
  791.  
  792. /*
  793.     前方スクロール
  794. */
  795. static void 
  796. line_f(void)
  797. {
  798.     if (lp < lpmx - 30) {
  799.         lp++;
  800. #if    SSCRL
  801.         TXRASCPY(8 * 256 + 7, 116, 3);
  802.         w_hs();
  803.         TXRASCPY(7 * 256 + 6, 116, 3);
  804.         w_hs();
  805.         TXRASCPY(6 * 256 + 5, 116, 3);
  806.         w_hs();
  807.         TXRASCPY(5 * 256 + 4, 116, 3);
  808.         w_hs();
  809. #else
  810.         if (!shift_on())
  811.             vsync();
  812.         TXRASCPY(8 * 256 + 4, 116, 3);
  813. #endif
  814.         p_lin(lp + 29, 29);
  815.     }
  816. }
  817.  
  818. #if SSCRL
  819. int
  820. w_hs()
  821. {
  822.     char *gpip = 0xe88001;
  823.  
  824.     while ((B_BPEEK(gpip) & 0x80) == 0)
  825.         ;
  826.     while (B_BPEEK(gpip) & 0x80)
  827.         ;
  828.  
  829.     return 0;
  830. }
  831. #endif
  832.  
  833.  
  834.  
  835. /*
  836.     ROM の電卓ルーチンバグ(D3破壊)対策
  837.     キー入力がある間捨てる(キースキャンする)
  838. */
  839. void
  840. check_keysns(void)
  841. {
  842.     asm("\
  843.     movem.l d3,-(sp)    \n\
  844. 0:    moveq #1,d0    * 1:B_KEYSNS \n\
  845.     trap #15    \n\
  846.     tst.l d0    \n\
  847.     beq 1f        \n\
  848.     moveq #0,d0    * 0:B_KEYINP \n\
  849.     trap #15    \n\
  850.     bra 0b        \n\
  851. 1:    movem.l (sp)+,d3" : : : "d0");
  852. }
  853.  
  854.  
  855. /*
  856.     ◎マーク非反転表示
  857. */
  858. void
  859. p_norev(void)
  860. {
  861.     int i, lno = lp;
  862.  
  863.     B_COLOR(3);
  864.     for (i = 1; i <= 30; i++) {
  865.         if (lno >= 0 && lno < lpmx && isTypeLine(lhp[lno])) {
  866.             B_LOCATE(0, i);
  867.             if (debugMode && lhp[lno][1] == VEXEC_CHAR) {
  868.                 B_COLOR(2);
  869.                 B_PUTC(L'◎');
  870.                 B_COLOR(3);
  871.             } else {
  872.                 B_PUTC(L'◎');
  873.             }
  874.         }
  875.         lno++;
  876.     }
  877. }
  878.  
  879.  
  880. /*
  881.     ◎マーク反転表示
  882. */
  883. static int revY;    // 反転表示した行
  884. void
  885. p_rev(int lin)
  886. {
  887.     p_norev();
  888.     B_PUTMES(9, 0, revY = lin + 1, 2 - 1, "◎");
  889. }
  890.  
  891.  
  892. /*
  893.     反転表示された '◎' を任意の文字に変える
  894. */
  895. void
  896. p_execmark(ushort c)
  897. {
  898.     B_COLOR(1);
  899.     B_LOCATE(0, revY);
  900.     B_PUTC(c);
  901.     B_COLOR(3);
  902. }
  903.  
  904. /*
  905.     選択された '◎' の色を変えて表示する
  906. */
  907. static void
  908. p_mark(int lin)
  909. {
  910.     p_norev();
  911.     B_PUTMES(1, 0, lin + 1, 2 - 1, "◎");
  912. }
  913.  
  914.  
  915. /*
  916.     1キー閲覧 (oneKeyView()) とその下請け関数
  917.  
  918.     スペースを押すたびに
  919.  
  920.         ◎の選択、実行
  921.         頁内に◎がもうなかったら次頁
  922.         EOFに達したら復帰
  923.  
  924.     相当の処理を順に進める
  925. */
  926. static uchar
  927. checkBreakPoint(const char *p)
  928. {
  929.     if (debugMode && *p++ == '\x1b' && *p++ == '[' && *p == 'm'
  930.       && (B_SFTSNS() & (LED_CODEIN | LED_KANA)) == LED_CODEIN) {
  931.         LEDMOD(2, 0);
  932.         w_open();
  933.         w_mes(1, "*BREAK POINT*");
  934.         w_wait(99);
  935.         w_close();
  936.         return selectedFlag = TRUE;
  937.     }
  938.     return FALSE;
  939. }
  940.  
  941. static int
  942. oneKeyLocateF(int y, uchar scrollFlag)
  943. {
  944.     int n, m, lpBak = lp;
  945.  
  946.     n = curLine;
  947.     if (y == exeLine)
  948.         n = y + 1;
  949.     else if (y >= 0 && y < lpmx)
  950.         n = y;
  951.     if (n >= lpmx && lp >= lpmx - 30)
  952.         goto RETURN_RETN;
  953.     else if (n < lp || n >= lp + 30)
  954.         n = lp;
  955.     m = lp + 29;
  956.     if (m >= lpmx)
  957.         m = lpmx - 1;
  958.     for (; n <= m; n++) {
  959.         if (isTypeLine(lhp[n]) || checkBreakPoint(lhp[n])) {
  960.             selectedFlag = TRUE;
  961.             break;
  962.         }
  963.     }
  964.     curLine = n;
  965.     m = n - lp;
  966.     if (!selectedFlag && n >= lpmx && lp >= lpmx - 30)
  967.         goto RETURN_RETN;
  968.     if (m >= 23) {
  969.         if (scrollFlag) {
  970.             while (m > 10 && lp < lpmx - 30) {
  971.                 lp++;
  972.                 TXRASCPY(8 * 256 + 4, 116, 3);
  973.                 p_lin(lp + 29, 29);
  974.                 m--;
  975.             }
  976.             p_fpt(0);
  977.         } else if (lp < lpmx - 30) {
  978.             curLine--;
  979.         }
  980.     }
  981.     if (selectedFlag)
  982.         setmspos(8, (m + 1) * 16 + 8);
  983.     else {
  984.         if (m > 0)
  985.             m--;
  986.         if (lpBak >= lpmx - 30) {
  987.             curLine = lpmx;
  988.             m = 29;
  989.         }
  990.         locateEol(m + 1);
  991.     }
  992.     return ONEKEY_CONT;
  993.  
  994. RETURN_RETN:
  995.     p_norev();
  996.     selectedFlag = FALSE;
  997.     exeLine = curLine = lpmx;
  998.     locateEol(30);
  999.  
  1000.     return ONEKEY_RETN;
  1001. }
  1002.  
  1003. static int
  1004. oneKeyLocateB(int y, uchar scrollFlag)
  1005. {
  1006.     int n, m, lpBak = lp;
  1007.  
  1008.     n = curLine;
  1009.     if (y == exeLine)
  1010.         n = y - 1;
  1011.     else if (y >= 0 && y < lpmx)
  1012.         n = y;
  1013.     if (n < 0 && lp == 0)
  1014.         goto RETURN_RETN;
  1015.     else if (n < lp || n >= lp + 30)
  1016.         n = lp + 29;
  1017.     if (n >= lpmx)
  1018.         n = lpmx - 1;
  1019.     m = lp;
  1020.     for (; n >= m; n--) {
  1021.         if (isTypeLine(lhp[n]) || checkBreakPoint(lhp[n])) {
  1022.             selectedFlag = TRUE;
  1023.             break;
  1024.         }
  1025.     }
  1026.     curLine = n;
  1027.     m = n - lp;
  1028.     if (!selectedFlag && n < 0 && lp <= 0)
  1029.         goto RETURN_RETN;
  1030.     if (m <= 6) {
  1031.         if (scrollFlag) {
  1032.             while (m < 19 && lp > 0) {
  1033.                 lp--;
  1034.                 TXRASCPY((116 + 3) * 256 + (120 + 3), 116, 0x8003);
  1035.                 p_lin(lp, 0);
  1036.                 m++;
  1037.             }
  1038.             p_fpt(0);
  1039.         } else if (lp > 0) {
  1040.             curLine++;
  1041.         }
  1042.     }
  1043.     if (selectedFlag)
  1044.         setmspos(8, (m + 1) * 16 + 8);
  1045.     else {
  1046.         if (m < 29)
  1047.             m++;
  1048.         if (lpBak <= 0) {
  1049.             curLine = -1;
  1050.             m = 0;
  1051.         }
  1052.         locateEol(m + 1);
  1053.     }
  1054.     return ONEKEY_CONT;
  1055.  
  1056. RETURN_RETN:
  1057.     p_norev();
  1058.     selectedFlag = FALSE;
  1059.     exeLine = curLine = -1;
  1060.     locateEol(1);
  1061.  
  1062.     return ONEKEY_RETN;
  1063. }
  1064.  
  1065. static int
  1066. oneKeyView(int x, int y, uchar scrollFlag)
  1067. {
  1068.     int stat;
  1069.  
  1070.     y = y / 16 - 1;
  1071.     if (x < 16 && y >= 0 && y < 30) {
  1072.         y += lp;
  1073.         if (selectedFlag && y == curLine) {
  1074.             while (space_on())
  1075.                 ;
  1076.             exeLine = curLine;
  1077.             return ONEKEY_EXEC;
  1078.         }
  1079.         if (B_SFTSNS() & LED_CODEIN)
  1080.             y = curLine;
  1081.     } else
  1082.         y = -1;
  1083.     selectedFlag = FALSE;
  1084.     if (backwardFlag)
  1085.         stat = oneKeyLocateB(y, scrollFlag);
  1086.     else
  1087.         stat = oneKeyLocateF(y, scrollFlag);
  1088.  
  1089.     while (space_on())
  1090.         ;
  1091.  
  1092.     return stat;
  1093. }
  1094.  
  1095.  
  1096. /*
  1097.     スペースキーのチェック
  1098.     (デバッグモードではコード入力キーの LED も同じ扱い)
  1099. */
  1100. static int
  1101. checkOneKeyView(void)
  1102. {
  1103.     if (codein_on()) {
  1104.         if (debugMode)
  1105.             return TRUE;
  1106.         LEDMOD(2, 0);
  1107.     }
  1108.     return space_on();
  1109. }
  1110.  
  1111.  
  1112. /*
  1113.     '◎' の検索
  1114. */
  1115. static void
  1116. locateTypeLine(int x, int y)
  1117. {
  1118.     short stat;
  1119.  
  1120.     etTab = init_et((etTab == 0) ? 40 : 10);
  1121.     if ((stat = oneKeyView(x, y, TRUE)) == ONEKEY_EXEC) {
  1122.         selectedFlag = FALSE;
  1123.         mspos(&x, &y);
  1124.         stat = oneKeyView(x, y, TRUE);
  1125.     }
  1126.     if (selectedFlag) {
  1127.         etTab = init_et(20);
  1128.         if (isTypeLine(lhp[curLine]))
  1129.             p_mark(curLine - lp);
  1130.         else
  1131.             p_norev();
  1132.     } else if (stat == ONEKEY_RETN)
  1133.         etTab = init_et(40);
  1134. }
  1135.  
  1136.  
  1137. /*
  1138.     行頭が '◎' (の内部コード) かどうか調べる
  1139. */
  1140. static int
  1141. isTypeLine(const uchar *s)
  1142. {
  1143.     return (s[0] == CTRL_CHAR && (s[1] | 0x20) == VEXEC_CHAR);
  1144. }
  1145.  
  1146.  
  1147. /*
  1148.     'TYPE=' (の内部コード) を探し、直後の文字位置を返す
  1149. */
  1150. static uchar *
  1151. searchType(const uchar *s)
  1152. {
  1153.     int n;
  1154.  
  1155.     while (n = dinstrchr(s, CTRL_CHAR)) {
  1156.         s += n;
  1157.         if (*s == TYPE_CHAR || *s == NULTYPE_CHAR)
  1158.             return s + 1;
  1159.     }
  1160.     return NULL;
  1161. }
  1162.  
  1163.  
  1164. /*
  1165.     '◎' の実行確認 (◎^[[m~TYPE=~)
  1166. */
  1167. static int
  1168. exeQuery(void)
  1169. {
  1170.     int x, y, bl, br;
  1171.  
  1172.     if (!debugMode || !strnEqu(lhp[exeLine] + 2, "\x1b[m", 3) || !codein_on())
  1173.         return TRUE;
  1174.  
  1175.     w_open();
  1176.     w_mes(0, "実行しますか?");
  1177.     w_mes(2, "左クリックで実行/右クリックでスキップ");
  1178.     wait_mb_off();
  1179.     do {
  1180.         dmsstat(&x, &y, &bl, &br);
  1181.     } while (!bl && !br && codein_on());
  1182.     w_close();
  1183.     wait_mb_off();
  1184.  
  1185.     return (bl && !br);
  1186. }
  1187.  
  1188.  
  1189. /*
  1190.     dtype() を呼ぶ
  1191. */
  1192. static void
  1193. callDtype(int lno)
  1194. {
  1195.     uchar *p;
  1196.  
  1197.     exeLine = curLine = lno;
  1198.     selectedFlag = FALSE;
  1199.     if (lno < lpmx && isTypeLine(lhp[lno])) {
  1200.         if ((p = searchType(lhp[lno])) != NULL
  1201.           || ++lno < lpmx && !isTypeLine(lhp[lno]) && (p = searchType(lhp[lno])) != NULL) {
  1202.             p_rev(curLine - lp);
  1203.             if (exeQuery()) {
  1204.                 dtype(p, FALSE);
  1205.                 if (debugMode && lhp[curLine][1] == EXEC_CHAR)
  1206.                     lhp[curLine][1] = VEXEC_CHAR;
  1207.             }
  1208.             p_fukki();
  1209.             p_rev(curLine - lp);
  1210.             mouse(1);
  1211.             wait_mb_off();
  1212.         }
  1213.     }
  1214. }
  1215.  
  1216.  
  1217. /*
  1218.     dexec() を呼ぶ
  1219. */
  1220. static void
  1221. callDexec(const char *command, int flag)
  1222. {
  1223.     dexec(command, flag);
  1224.     mouse(1);
  1225.     selectedFlag = FALSE;
  1226. }
  1227.  
  1228.  
  1229. /*
  1230.     マウスカーソルがメインスクリーンの (x, 0)~(x, 15) にあったら
  1231.     ちょっとずらす
  1232. */
  1233. static void
  1234. adjMspos(void)
  1235. {
  1236.     int mx, my;
  1237.  
  1238.     mspos(&mx, &my);
  1239.     if (mx < 16 && my >= 1*16 && my < 31*16)
  1240.         setmspos(16, my);
  1241. }
  1242.  
  1243.  
  1244. /*
  1245.     指定行の (表示上の) 行末にマウスカーソルを位置付ける
  1246. */
  1247. asm("
  1248. _locateEol::
  1249.     suba.l    a1,a1
  1250.     moveq.l    #$81,d0        *B_SUPER
  1251.     trap    #15
  1252.     move.l    d0,-(sp)
  1253.  
  1254.     moveq.l    #7+4,d0
  1255.     move.l    4+4(sp),d2
  1256.     lsl.l    d0,d2
  1257.     add.l    #$e00000,d2
  1258.     movea.l    d2,a0
  1259.     moveq.l    #96-1-1,d1
  1260.     tst.w    _GMODE
  1261.     beq    @f
  1262.     moveq.l    #64-1-1,d1
  1263. @@:    lea.l    1(a0,d1.l),a0
  1264.     movea.l    a0,a1
  1265.     adda.l    #1024*128,a1
  1266.     lea.l    $e8002a,a2    *CRTC R21
  1267.     move.w    (a2),d0    *{
  1268.     move.w    #0,(a2)
  1269.  
  1270. @@:    move.b    -(a0),d2
  1271.     or.b    $0080(a0),d2
  1272.     or.b    $0100(a0),d2
  1273.     or.b    $0180(a0),d2
  1274.     or.b    $0200(a0),d2
  1275.     or.b    $0280(a0),d2
  1276.     or.b    $0300(a0),d2
  1277.     or.b    $0380(a0),d2
  1278.     or.b    $0400(a0),d2
  1279.     or.b    $0480(a0),d2
  1280.     or.b    $0500(a0),d2
  1281.     or.b    $0580(a0),d2
  1282.     or.b    $0600(a0),d2
  1283.     or.b    $0680(a0),d2
  1284.     or.b    $0700(a0),d2
  1285.     or.b    $0780(a0),d2
  1286.     or.b    -(a1),d2
  1287.     or.b    $0080(a1),d2
  1288.     or.b    $0100(a1),d2
  1289.     or.b    $0180(a1),d2
  1290.     or.b    $0200(a1),d2
  1291.     or.b    $0280(a1),d2
  1292.     or.b    $0300(a1),d2
  1293.     or.b    $0380(a1),d2
  1294.     or.b    $0400(a1),d2
  1295.     or.b    $0480(a1),d2
  1296.     or.b    $0500(a1),d2
  1297.     or.b    $0580(a1),d2
  1298.     or.b    $0600(a1),d2
  1299.     or.b    $0680(a1),d2
  1300.     or.b    $0700(a1),d2
  1301.     or.b    $0780(a1),d2
  1302.     dbne    d1,@b
  1303.  
  1304.     move.w    d0,(a2)    *}
  1305.     addq.w    #1,d1
  1306.     cmpi.w    #2,d1
  1307.     bcc    @f
  1308.     moveq.l    #2,d1
  1309. @@:    lsl.w    #3,d1
  1310.     addq.w    #4,d1
  1311.     swap.w    d1
  1312.     move.w    4+2+4(sp),d1
  1313.     lsl.w    #4,d1
  1314.     moveq.l    #$76,d0        *MS_CURST
  1315.     trap    #15
  1316.  
  1317. .if 0
  1318.     move.l    (sp)+,d0
  1319.     bmi    @f
  1320.     movea.l    d0,a1
  1321. .else
  1322.     movea.l    (sp)+,a1
  1323. .endif
  1324.     moveq.l    #$81,d0        *B_SUPER
  1325.     trap    #15
  1326. @@:    rts
  1327. ");
  1328.  
  1329.  
  1330. /*
  1331.     デバッグモードの ON/OFF (OPT.2+HELP)
  1332. */
  1333. static void
  1334. inOutDebugMode(void)
  1335. {
  1336.     char temp[64];
  1337.  
  1338.     debugMode = !debugMode;
  1339.     w_open();
  1340.     sprintf(temp, "デバッグモード%sます", (debugMode) ? "に入り" : "を抜け");
  1341.     w_mes(1, temp);
  1342.     w_wait(60);
  1343.     p_scr();
  1344. }
  1345.  
  1346. /*
  1347.     デバッグモード+コード入力+ローマ字orかな 時の“端折り”チェック
  1348. */
  1349. static int checkRapidExec(void)
  1350. {
  1351.     int n;
  1352.     ushort shiftKeys;
  1353.  
  1354.     if (!debugMode)
  1355.         return FALSE;
  1356.     shiftKeys = B_SFTSNS();
  1357.     if (!(shiftKeys & LED_CODEIN) || !(shiftKeys & (LED_ROMA | LED_KANA)))
  1358.         return FALSE;
  1359.     for (n = 0; n < lpmx; n++)
  1360.         if (isTypeLine(lhp[n]))
  1361.             return FALSE;
  1362.     return TRUE;
  1363. }
  1364.